# -*- coding:utf-8 -*-
"""
@Author : 审心
@Time : 2023/4/28 15:17
"""
from dataclasses import dataclass
from typing import Tuple, List, Optional, Iterable
import xlwings as xw
from DrissionPage import WebPage
from openpyxl.utils import get_column_letter
from xlwings import Sheet

from autoTask.taobao.sycm.goods.findMarketRank.ExcelOperation import del_row, get_ignore_del_row_num, \
    get_sheet_to_row_map_list
from common.utils import ObjUtil, ExcelUtil
from common.utils.ExcelUtil import XwRowMap


@dataclass
class FilterAction:
    """
    过滤数据操作

    Attributes:
        price_scope (List[int]): 包含最小价格和最大价格的元组。
        title_contain_str (List[str]): 包含在标题中的字符串列表。如果一个标题中包含了这个列表中的所有字符串，则该标题将被保留。
        title_not_contain_str (List[str]): 不包含在标题中的字符串列表。如果一个标题中包含了这个列表中的任何一个字符串，则该标题将被过滤掉。
    """
    price_scope: Optional[List[int]] = None
    title_contain_str: Optional[List[str]] = None
    title_not_contain_str: Optional[List[str]] = None

    def __call__(self, data_list: Iterable[any]) -> List:
        if ObjUtil.all_values_empty(self.price_scope, self.title_contain_str, self.title_not_contain_str):
            return list(data_list)
        return [data for data in data_list if self.filter(data)]

    def filter(self, item: list):
        price = item[17]
        title = item[1]
        if self.price_scope and price >= self.price_scope[1] or price <= self.price_scope[0]:
            return False
        if self.title_contain_str and any(s_ not in title for s_ in self.title_contain_str):
            return False
        if self.title_not_contain_str and any(s_ in title for s_ in self.title_not_contain_str):
            return False
        return True


@dataclass
class FilterActionV2:
    """
    过滤数据操作 V2 直接使用 excel 表进行过滤
    Attributes:
        min_price_1 : 最低可客单价 1步过滤参数
        sort_amount_top_r : 交易金额倒叙保留前 * 百分比 (例如: 前百分之50的不)
        sort_search_people_top_r : 搜索人数倒叙保留前 * 百分比
        sort_min_uv_price: 排序后,即 排除不需要删除的行后 UV 价值小于此值的删除
        sort_min_price: 排序后,即 排除不需要删除的行后 客单价小于此值的删除
        title_contain_str: 商品信息包含此列表所有字符串的保留
        title_not_contain_str: 商品信息不包含此列表所有字符串的保留
    """
    min_price_1: Optional[float]
    sort_amount_top_r: Optional[int]
    sort_search_people_top_r: Optional[int]
    sort_min_uv_price: Optional[float]
    sort_min_price: Optional[float]
    title_contain_str: Optional[List[str]]
    title_not_contain_str: Optional[List[str]]

    def __call__(self, excel_path: str):
        if ObjUtil.all_values_empty(self.min_price_1, self.sort_amount_top_r, self.sort_search_people_top_r,
                                    self.sort_min_uv_price, self.sort_min_price, self.title_contain_str,
                                    self.title_not_contain_str):
            return
        app = xw.App(visible=True)
        sht: Sheet = app.books.open(excel_path).sheets[0]
        try:
            # 将 sheet 转为自定义 行号与数据映射的对列表
            base_list: List[XwRowMap] = get_sheet_to_row_map_list(sht, 'B', 1)
            # 过滤
            filter_list = self.filter(sht, base_list)
            del_row(sht, [b.num for b in base_list if b not in filter_list])
            # 自动设置列宽
            sht.range('B1').expand('table').columns.autofit()
            sht.range('E1').expand('table').columns.autofit()
            # 将链接列转为超链接
            col = get_column_letter(sht.range("1:1").value.index("商品链接") + 1)
            ExcelUtil.xw_col_content_to_link(sht, f"{col}2")
        finally:
            sht.book.save()
            sht.book.close()
            app.quit()

    def filter(self, sht: Sheet, filter_list: List[XwRowMap]) -> List[XwRowMap]:
        """
        根据对象数据过滤
        :param sht: Sheet 对象
        :param filter_list: 需要过滤的列表
        :return: 满足条件的 即,需要保留的元素列表
        """
        # 客单价过滤
        filter_list = XwRowMap.filter_row_map_by_col(filter_list,
                                                     sht.range("1:1").value.index("客单价"),
                                                     lambda col: float(col) > self.min_price_1,
                                                     before_condition=ObjUtil.not_has_none(self.min_price_1))
        if self.sort_amount_top_r and self.sort_search_people_top_r:
            # 排序后获取本次过滤必须保留的数据行号
            i_row_num = get_ignore_del_row_num(filter_list, amount_top_r=self.sort_amount_top_r,
                                               search_people_top_r=self.sort_search_people_top_r)
            filter_list = XwRowMap.filter_row_map_by_col(filter_list,
                                                         sht.range("1:1").value.index("UV价值"),
                                                         lambda col: col > self.sort_min_uv_price, i_row_num,
                                                         ObjUtil.not_has_none(self.sort_min_uv_price))
            filter_list = XwRowMap.filter_row_map_by_col(filter_list,
                                                         sht.range("1:1").value.index("客单价"),
                                                         lambda col: col > self.sort_min_price, i_row_num,
                                                         ObjUtil.not_has_none(self.sort_min_price))
        filter_list = XwRowMap.filter_row_map_by_col(filter_list,
                                                     sht.range("1:1").value.index("商品信息"),
                                                     lambda col: all(s not in col for s in self.title_not_contain_str),
                                                     before_condition=ObjUtil.is_not_empty(self.title_not_contain_str))
        filter_list = XwRowMap.filter_row_map_by_col(filter_list,
                                                     sht.range("1:1").value.index("商品信息"),
                                                     lambda col: all(s in col for s in self.title_contain_str),
                                                     before_condition=ObjUtil.is_not_empty(self.title_contain_str))
        return filter_list
